package com.ruoyi.sl.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.sl.domain.*;
import com.ruoyi.sl.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.sl.service.ISlMonthOfcService;

/**
 * 行政固定工资Service业务层处理
 * 
 * @author admin
 * @date 2024-06-14
 */
@Service
public class SlMonthOfcServiceImpl implements ISlMonthOfcService 
{
    @Autowired
    private SlMonthOfcMapper slMonthOfcMapper;
    @Autowired
    private SlOfcLeaveMapper slOfcLeaveMapper;
    @Autowired
    private SlLeaveRecordMapper slLeaveRecordMapper;
    @Autowired
    private SlOfcperformanceMapper slOfcperformanceMapper;
    @Autowired
    private SlOfcabsenceMapper slOfcabsenceMapper;
    @Autowired
    private SlWerrorMapper slWerrorMapper;
    /**
     * 查询行政固定工资
     * 
     * @param ofcmpayId 行政固定工资主键
     * @return 行政固定工资
     */
    @Override
    public SlMonthOfc selectSlMonthOfcByOfcmpayId(Long ofcmpayId)
    {
        return slMonthOfcMapper.selectSlMonthOfcByOfcmpayId(ofcmpayId);
    }

    /**
     * 查询行政固定工资列表
     * 
     * @param slMonthOfc 行政固定工资
     * @return 行政固定工资
     */
    @Override
    public List<SlMonthOfc> selectSlMonthOfcList(SlMonthOfc slMonthOfc)
    {
        return slMonthOfcMapper.selectSlMonthOfcList(slMonthOfc);
    }

    /**
     * 条件查询行政工资列表
     *
     * @param slMonthOfc 行政增工资
     * @return 车间工资集合
     */
    public List<SlMonthOfc> selectSlMonthOfcListByRange(SlMonthOfc slMonthOfc){
        return slMonthOfcMapper.selectSlMonthOfcListByRange(slMonthOfc);
    }


    //根据日期姓名查询工资,返回格式转换为了计件和行政合并
    @Override
    public List<SlMonthPay> selectSlMonthOfcByUserAndDate(String ofcmpayYear,String ofcmpayMonth,String userName){
        return slMonthOfcMapper.selectSlMonthOfcByUserAndDate(ofcmpayYear,ofcmpayMonth,userName);
    }


    /**
     * 新增行政固定工资
     * 
     * @param slMonthOfc 行政固定工资
     * @return 结果
     */
    @Transactional
    @Override
    public int insertSlMonthOfc(SlMonthOfc slMonthOfc)
    {
        slMonthOfc.setCreateTime(DateUtils.getNowDate());
        int rows = slMonthOfcMapper.insertSlMonthOfc(slMonthOfc);
        return rows;
    }

    /**
     * 修改行政固定工资
     * 
     * @param slMonthOfc 行政固定工资
     * @return 结果
     */
    @Transactional
    @Override
    public int updateSlMonthOfc(SlMonthOfc slMonthOfc)
    {
        slMonthOfc.setUpdateTime(DateUtils.getNowDate());

        return updateOfcMonthPay(slMonthOfc);
    }

    /**
     * 固定工资变为历史
     *
     * @return 结果
     */
    @Override
    public int updateSlMonthOfcToHistory(){
        return slMonthOfcMapper.updateSlMonthOfcToHistory();
    }

    /**
     * 批量删除行政固定工资
     * 
     * @param ofcmpayIds 需要删除的行政固定工资主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteSlMonthOfcByOfcmpayIds(Long[] ofcmpayIds)
    {
        return slMonthOfcMapper.deleteSlMonthOfcByOfcmpayIds(ofcmpayIds);
    }

    /**
     * 删除行政固定工资信息
     * 
     * @param ofcmpayId 行政固定工资主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteSlMonthOfcByOfcmpayId(Long ofcmpayId)
    {
        return slMonthOfcMapper.deleteSlMonthOfcByOfcmpayId(ofcmpayId);
    }

    //根据日期删除工资
    @Override
    public int deleteSlMonthOfcByDate(String ofcmpayYear,String ofcmpayMonth){
        return slMonthOfcMapper.deleteSlMonthOfcByDate(ofcmpayYear,ofcmpayMonth);
    }

    /**
     * 更新指定工资
     *
     * @param slMonthOfc 工资信息
     * @return 结果
     */
    public int updateOfcMonthPay(SlMonthOfc slMonthOfc){
        //个人比例
        BigDecimal personPer = slMonthOfc.getPersonalPerformance().divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.DOWN);
        //部门比例
        BigDecimal deptPer = slMonthOfc.getDeptPerformance().divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.DOWN);
        //发薪比例
        BigDecimal payPer = BigDecimal.valueOf(1).subtract(personPer).subtract(deptPer).setScale(2, RoundingMode.DOWN);
        //出勤天速
        BigDecimal attendanceDay = slMonthOfc.getAttendanceDay();
        //满勤天数
        BigDecimal fullDay = slMonthOfc.getFullDay();
        //缺勤信息 天数和工资
        SlOfcLeave slOfcLeave =  slOfcLeaveMapper.selectSlOfcLeaveByOfcmpayId(slMonthOfc.getOfcmpayId());
        //缺勤天数  出勤-缺勤>满勤 = 满勤
        BigDecimal absenceDay = slOfcLeave.getLeaveAbsenceNum().add(slOfcLeave.getInjuryLeaveNum()).add(slOfcLeave.getSickLeaveNum()).add(slOfcLeave.getMarriageLeaveNum()).add(slOfcLeave.getBereavementLeaveNum()).add(slOfcLeave.getMaternityLeaveNum()).add(slOfcLeave.getPaternityLeaveNum()).setScale(2, RoundingMode.DOWN);
        if((attendanceDay.subtract(absenceDay)).compareTo(fullDay)>=0){
            absenceDay = BigDecimal.ZERO;
        }
        slMonthOfc.setAbsenceDay(absenceDay);
        //实际出勤天数
        BigDecimal realAttendanceDay = fullDay.subtract(absenceDay).setScale(2, RoundingMode.DOWN);
        //出勤天数
        slMonthOfc.setAttendanceDay(realAttendanceDay);
        //全面薪酬
        BigDecimal totalReward = slMonthOfc.getTotalReward();
        //出勤固定（全面薪酬*出勤天数*（1-个人绩效比例-部门绩效比例）/满勤天数）
        BigDecimal attendancePay = totalReward.multiply(realAttendanceDay).multiply(payPer).divide(fullDay,2, RoundingMode.DOWN).setScale(2, RoundingMode.DOWN);
        slMonthOfc.setAttendancePay(attendancePay);
        //工龄工资
        int workingAge = slMonthOfc.getWorkingAge();
        BigDecimal ageBase = slMonthOfc.getAgeBase();
        BigDecimal ageAllpay = ageBase.multiply(BigDecimal.valueOf(workingAge)).multiply(realAttendanceDay).divide(fullDay,2, RoundingMode.DOWN).setScale(2, RoundingMode.DOWN);
        //BigDecimal agePay = ageAllpay.multiply(payPer).setScale(2, BigDecimal.ROUND_DOWN);
        slMonthOfc.setAgeAllpay(ageAllpay);
        //slMonthOfc.setAgePay(agePay);
        //餐补
        BigDecimal mealBase = slMonthOfc.getMealBase();
        BigDecimal mealAllowance = mealBase.multiply(realAttendanceDay).setScale(2, RoundingMode.DOWN);
        slMonthOfc.setMealAllowance(mealAllowance);
        //早班补贴  次数X基数
        BigDecimal earlyBase = slMonthOfc.getEarlyBase();
        int earlyNum = slMonthOfc.getEarlyNum();
        BigDecimal earlyShift = earlyBase.multiply(BigDecimal.valueOf(earlyNum)).setScale(2, RoundingMode.DOWN);
        slMonthOfc.setEarlyShift(earlyShift);
        //晚班补助
        BigDecimal nightBas = slMonthOfc.getNightBase();
        int nightNum = slMonthOfc.getNightNum();
        BigDecimal nightShift = nightBas.multiply(BigDecimal.valueOf(nightNum)).setScale(2, RoundingMode.DOWN);
        slMonthOfc.setEarlyShift(nightShift);
        //加班补助
        BigDecimal overtimeAllallowance= slMonthOfc.getOvertimeAllallowance();
        //BigDecimal overtimeAllowance = overtimeAllallowance.multiply(payPer).setScale(2, BigDecimal.ROUND_DOWN);
        //slMonthOfc.setOvertimeAllowance(overtimeAllowance);
        //应发工资=产假工资+工伤假工资+病假工资+出勤固定+出勤工龄工资+餐补+高温补贴+早班补助+晚班补助+加班补助
        BigDecimal wagePayable = slOfcLeave.getInjuryLeavePay().add(slOfcLeave.getSickLeavePay()).add(slOfcLeave.getMarriageLeavePay()).add(slOfcLeave.getBereavementLeavePay()).add(slOfcLeave.getMaternityLeavePay()).add(slOfcLeave.getPaternityLeavePay()).setScale(2, RoundingMode.DOWN);
        wagePayable = wagePayable.add(attendancePay).add(ageAllpay).add(mealAllowance).add(slMonthOfc.getHighTemperature()).add(earlyShift).add(nightShift).add(overtimeAllallowance).add(slMonthOfc.getOtherSubsidy()).setScale(2, RoundingMode.DOWN);
        slMonthOfc.setWagePayable(wagePayable);
        //每月实发=应发工资-公积金-社保-代扣税
        BigDecimal netSalary = wagePayable.subtract(slMonthOfc.getProvidentFund()).subtract(slMonthOfc.getSocialSecurity()).subtract(slMonthOfc.getTaxDeduction()).setScale(2,RoundingMode.DOWN);
        slMonthOfc.setNetSalary(netSalary);
        //gengxin
        slMonthOfcMapper.updateSlMonthOfc(slMonthOfc);
        //-------------------绩效工资-------------------
        SlOfcperformance slOfcperformance = slOfcperformanceMapper.selectSlOfcperformanceByOfcmpayId(slMonthOfc.getOfcmpayId());
        //绩效天数
        BigDecimal performanceDay = realAttendanceDay;
        slOfcperformance.setPerformanceDay(performanceDay);
        //绩效缺勤天数
        BigDecimal perAbsenceDay = absenceDay;
        if(absenceDay.compareTo(BigDecimal.valueOf(2))<=0){
            perAbsenceDay = BigDecimal.ZERO;
        }
        slOfcperformance.setAbsenceDay(perAbsenceDay);
        //绩效基数
        BigDecimal performanceBase = totalReward.add(ageAllpay).add(overtimeAllallowance).add(earlyBase.multiply(BigDecimal.valueOf(earlyNum))).add(nightBas.multiply(BigDecimal.valueOf(nightNum))).setScale(2, RoundingMode.DOWN);
        performanceBase = performanceBase.multiply(personPer.add(deptPer)).setScale(2, BigDecimal.ROUND_DOWN);
        if (perAbsenceDay.compareTo(BigDecimal.valueOf(3))>=0){
            performanceBase = performanceBase.multiply(performanceDay).divide(fullDay,2, RoundingMode.DOWN).setScale(2, RoundingMode.DOWN);
        }
        slOfcperformance.setPerformanceBase(performanceBase);
        //扣发出勤绩效
        SlOfcabsence slOfcabsence = slOfcabsenceMapper.selectSlOfcabsenceByAbsenceDay(perAbsenceDay);
        BigDecimal performance = BigDecimal.ZERO;
        if (StringUtils.isNotNull(slOfcabsence)){
            performance = performanceBase.multiply(slOfcabsence.getPerformance().divide(BigDecimal.valueOf(100),2, RoundingMode.DOWN)).setScale(2, BigDecimal.ROUND_DOWN);
        }
        slOfcperformance.setPerformanceDeduction(performance);
        //工作绩效(工作绩效+新的工作绩效)
        BigDecimal deduction = slOfcperformance.getDeduction();
        List<SlWerror> slWerrorList = slWerrorMapper.selectSlWerrorByUserName(slMonthOfc.getUserName());
        if (StringUtils.isNotEmpty(slWerrorList)){
            for (SlWerror slWerror : slWerrorList) {
                deduction = deduction.add(slWerror.getWerrorFine());
                //记录该工作绩效被哪个工资单扣减了，避免重复扣减
                slWerror.setMpayId(slMonthOfc.getOfcmpayId());
            }
        }
        slOfcperformance.setDeduction(deduction);
        //剩余绩效
        BigDecimal performanceResidue = performanceBase.subtract(performance).subtract(deduction).setScale(2, BigDecimal.ROUND_DOWN);
        slOfcperformance.setPerformanceResidue(performanceResidue);
        //gengxin
        slOfcperformanceMapper.updateSlOfcperformance(slOfcperformance);

        //更新工作绩效
        for (SlWerror slWerror : slWerrorList) {
            slWerrorMapper.updateSlWerror(slWerror);
        }

        return 1;
    }

    /**
     * 更新指定请假工资
     *
     * @param ofcmpayId 工资主键
     */
    @Override
    public void updateOfcMonthLeavePay(Long ofcmpayId){
        //删除工资的请假信息
        slOfcLeaveMapper.deleteSlOfcLeaveByOfcmpayId(ofcmpayId);
        //请假记录
        List<SlLeaveRecord> slLeaveRecordList =  slLeaveRecordMapper.selectSlLeaveRecordByOfcmpayId(ofcmpayId);
        if (StringUtils.isNotEmpty(slLeaveRecordList)) {
            //请假工资
            SlOfcLeave slOfcLeave = new SlOfcLeave();
            slOfcLeave.setOfcmpayId(ofcmpayId);
            slOfcLeave.setLeaveAbsenceNum(BigDecimal.ZERO);
            slOfcLeave.setInjuryLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setInjuryLeavePay(BigDecimal.ZERO);
            slOfcLeave.setSickLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setSickLeavePay(BigDecimal.ZERO);
            slOfcLeave.setMarriageLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setMarriageLeavePay(BigDecimal.ZERO);
            slOfcLeave.setBereavementLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setBereavementLeavePay(BigDecimal.ZERO);
            slOfcLeave.setMaternityLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setMaternityLeavePay(BigDecimal.ZERO);
            slOfcLeave.setPaternityLeaveNum(BigDecimal.ZERO);
            slOfcLeave.setPaternityLeavePay(BigDecimal.ZERO);

            for (SlLeaveRecord slLeaveRecord : slLeaveRecordList) {
                Long vacationId = slLeaveRecord.getVacationId();
                //1事假2工伤假3病假4婚假5丧假6产假7陪产假
                if(vacationId==1){
                    slOfcLeave.setLeaveAbsenceNum(slOfcLeave.getLeaveAbsenceNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==2) {
                    slOfcLeave.setInjuryLeaveNum(slOfcLeave.getInjuryLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setInjuryLeavePay(slOfcLeave.getInjuryLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==3) {
                    slOfcLeave.setSickLeaveNum(slOfcLeave.getSickLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setSickLeavePay(slOfcLeave.getSickLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==4) {
                    slOfcLeave.setMarriageLeaveNum(slOfcLeave.getMarriageLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setMarriageLeavePay(slOfcLeave.getMarriageLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==5) {
                    slOfcLeave.setBereavementLeaveNum(slOfcLeave.getBereavementLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setBereavementLeavePay(slOfcLeave.getBereavementLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==6) {
                    slOfcLeave.setMaternityLeaveNum(slOfcLeave.getMaternityLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setMaternityLeavePay(slOfcLeave.getMaternityLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                } else if (vacationId==7) {
                    slOfcLeave.setPaternityLeaveNum(slOfcLeave.getPaternityLeaveNum().add(slLeaveRecord.getLeaveDay()).setScale(2, BigDecimal.ROUND_DOWN));
                    slOfcLeave.setPaternityLeavePay(slOfcLeave.getPaternityLeavePay().add(slLeaveRecord.getVacationPay()).setScale(2, BigDecimal.ROUND_DOWN));
                }
            }
            slOfcLeaveMapper.insertSlOfcLeave(slOfcLeave);

            updateOfcMonthPay(slMonthOfcMapper.selectSlMonthOfcByOfcmpayId(ofcmpayId));
        }
    }



}
